package grex.Nodes;

import grex.Data.Prediction;
import grex.Data.PredictionContainer;

public class If extends Node {

    private static final int NROFCILDREN = 3;
    private static final double TRUE = 1;
    
    final int CONDITION = 0;

    public If() {
        super(NROFCILDREN);
    }

    public synchronized void execute(Node parent, PredictionContainer data, int mode) throws GeneException {
        this.parent = parent;

        Node[] childs = this.getChildren();
        if(mode == Node.TRAIN_MODE){
            if(!modified){
                return;                
            }
            else
                modified=false;        
        }    //*/  


        //contidtion is tricky when optimzing needs to be run every time, revise!
        childs[CONDITION].execute(this, data, mode);
        PredictionContainer left, right;
        left = new PredictionContainer(data.size());
        right = new PredictionContainer(data.size());
        for (Prediction p : data.values()) {
            if (p.getCondition()) {
                left.put(p.getInstance(), p);
            } else {
                right.put(p.getInstance(), p);
            }
        }
            childs[1].execute(this, left, mode);
            childs[2].execute(this, right, mode);

        if (mode == Node.CLEAN_MODE && parent != this && parent != null) {
            //   childs = this.getChildren();
            Node[] parents = parent.getChildren();

            if (childs[1] instanceof ITerminal && childs[2] instanceof ITerminal) {
                if (childs[1].equals(childs[2])) { //Equal leaves
                    //    if (((ITerminal) childs[1]).getCount() > 0) {
                    if (parents[1] == this) {
                        parents[1] = childs[1];
                        childs[1].setParent(parent);
                        return;
                    } else {
                        parents[2] = childs[1];
                        childs[1].setParent(parent);
                        return;
                    }
                }
            }

            if (childs[1] instanceof ITerminal) {
                if (((ITerminal) childs[1]).getCount() == 0) {// || childs[1].equals(childs[2])) { //if empty leaf or both leaves predict the same class replace faqther with leave.
                    if (parents[1] == this) {
                        parents[1] = childs[2];
                        //    childs[2].setParent(parents[1]);
                        childs[2].setParent(parent);
                        return;
                    } else {
                        parents[2] = childs[2];
                        // childs[2].setParent(parents[2]);
                        childs[2].setParent(parent);
                        return;
                    }

                }
            }

            if (childs[2] instanceof ITerminal) {
                if (((ITerminal) childs[2]).getCount() == 0) {//Here equal prediction does not need to be set since it is already tested above.
                    if (parents[1] == this) {
                        parents[1] = childs[1];
                        // childs[1].setParent(parents[1]);
                        childs[1].setParent(parent);
                        return;
                    } else {
                        parents[2] = childs[1];
                        //childs[1].setParent(parents[2]);
                        childs[1].setParent(parent);
                        return;
                    }
                }
            }

        }
            //*/
    }

    public boolean equals(Object o) {
        if (o instanceof If) {
            If f = (If) o;
            return getChildren()[0].equals(f.getChildren()[0]);
        }
        return false;
    }

    public Object clone() {
        If newIf = new If();
        newIf.setOptions(ops);
        cloneChildren(newIf);
//        newIf.setParent(parent);
        newIf.modified = modified;
        /*     if(!modified){
        newIf.left = left.clone();
        newIf.right = right.clone();
        }//*/
        return newIf;
    }

    public String toString() {
        /*Node[] childs = this.getChildren();
        Node[] condition = childs[0].getChildren();
        String tmp = "if " + childs[0];
        for (int i = 0; i < condition.length; i++) {
        tmp += " " +condition[i];
        }*/
        return "if";
    }
}
